#include <fermat/libttp/http_common_header.h>
#include <unordered_map>

namespace fermat {
namespace libhttp {

/*!
* 
* Cache-Control
* Connection
* Content-Disposition
* Content-Encoding
* Content-Language
* Content-Length
* Content-Location
* Content-MD5
* Content-Range
* Content-Type
* Cookie
* DNT
* Date
* ETag
* Expect
* Expires
* From
* Front-End-Https
* Host
* If-Match
* If-Modified-Since
* If-None-Match
* If-Range
* If-Unmodified-Since
* Keep-Alive
* Last-Modified
* Link
* Location
* Max-Forwards
* Origin
* P3P
* Pragma
* Proxy-Authenticate
* Proxy-Authorization
* Proxy-Connection
* Range
* Referer
* Refresh
* Retry-After
* Server
* Set-Cookie
* Strict-Transport-Security
* TE
* Timestamp
* Trailer
* Transfer-Encoding
* Upgrade
* User-Agent
* VIP
* Vary
* Via
* WWW-Authenticate
* Warning
* Accept
* Accept-Charset
* Accept-Datetime
* Accept-Encoding
* Accept-Language
* Accept-Ranges
* Access-Control-Allow-Credentials
* Access-Control-Allow-Headers
* Access-Control-Allow-Methods
* Access-Control-Allow-Origin
* Access-Control-Expose-Headers
* Access-Control-Max-Age
* Access-Control-Request-Headers
* Access-Control-Request-Method
* Age
* Allow
* Alt-Svc
* Authorization
* X-Accel-Redirect
* X-Content-Security-Policy-Report-Only
* X-Content-Type-Options
* X-Forwarded-For
* X-Forwarded-Proto
* X-Frame-Options
* X-Powered-By
* X-Real-IP
* X-Requested-With
* X-UA-Compatible
* X-Wap-Profile
* X-XSS-Protection
* F-Debug
*/
struct CommonHeaderMap{
	std::unordered_map<std::string, HttpHeaderCode>  map;
	std::unordered_map<std::string, HttpHeaderCode>  rmap;
	CommonHeaderMap()
	{
		init_map("Cache-Control", HttpHeaderCode::kHttpHeaderCacheControl);
		init_map("Connection", HttpHeaderCode::kHttpHeaderConnection);
		init_map("Content-Disposition", HttpHeaderCode::kHttpHeaderContentDisposition);
		init_map("Content-Encoding", HttpHeaderCode::kHttpHeaderContentEncoding);
		init_map("Content-Language", HttpHeaderCode::kHttpHeaderContentLanguage);
		init_map("Content-Length", HttpHeaderCode::kHttpHeaderContentLength);
		init_map("Content-Location", HttpHeaderCode::kHttpHeaderContentLocation);
		init_map("Content-MD5", HttpHeaderCode::kHttpHeaderContentMD5);
		init_map("Content-Range", HttpHeaderCode::kHttpHeaderContentRange);
		init_map("Content-Length", HttpHeaderCode::kHttpHeaderContentLength);
		init_map("Content-Type", HttpHeaderCode::kHttpHeaderContentType);
		init_map("Cookie", HttpHeaderCode::kHttpHeaderCookie);
		init_map("DNT", HttpHeaderCode::kHttpHeaderDNT);
		init_map("Date", HttpHeaderCode::kHttpHeaderEtag);
		init_map("Expect", HttpHeaderCode::kHttpHeaderExpect);
		init_map("Expires", HttpHeaderCode::kHttpHeaderExpires);
		init_map("From", HttpHeaderCode::kHttpHeaderFrom);
		init_map("Front-End-Https", HttpHeaderCode::kHttpHeaderFrontEndHttps;
		init_map("Host", HttpHeaderCode::kHttpHeaderHost);
		init_map("If-Match", HttpHeaderCode::kHttpHeaderIfMatch);
		init_map("If-Modified-Since", HttpHeaderCode::kHttpHeaderIfModifySince);
		init_map("If-None-Match", HttpHeaderCode::kHttpHeaderIfNoneMatch);
		init_map("If-Range", HttpHeaderCode::kHttpHeaderIfRange);
		init_map("If-Unmodified-Since", HttpHeaderCode::kHttpHeaderIfUnmodifiedSice);
		init_map("Keep-Alive", HttpHeaderCode::kHttpHeaderKeepAlive);
		init_map("Last-Modified", HttpHeaderCode::kHttpHeaderLastModified);
		init_map("Link", HttpHeaderCode::kHttpHeaderLink);
		init_map("Location", HttpHeaderCode::kHttpHeaderLocation);
		init_map("Max-Forwards", HttpHeaderCode::kHttpHeaderMaxForwards);
		init_map("Origin", HttpHeaderCode::kHttpHeaderOrigin);
		init_map("P3P", HttpHeaderCode::kHttpHeaderP3p);
		init_map("Pragma", HttpHeaderCode::kHttpHeaderPragma);
		init_map("Proxy-Authenticate", HttpHeaderCode::kHttpHeaderProxyAuthenticate);
		init_map("Proxy-Authorization", HttpHeaderCode::kHttpHeaderProxyAuthorization);
		init_map("Proxy-Connection", HttpHeaderCode::kHttpHeaderProxyConnection);
		init_map("Range", HttpHeaderCode::kHttpHeaderRange);
		init_map("Referer", HttpHeaderCode::kHttpHeaderReferer);
		init_map("Refresh", HttpHeaderCode::kHttpHeaderRefresh);
		init_map("Retry-After", HttpHeaderCode::kHttpHeaderRetryAfter);
		init_map("Server", HttpHeaderCode::kHttpHeaderServer);
		init_map("Set-Cookie", HttpHeaderCode::kHttpHeaderSetCookie);
		init_map("Strict-Transport-Security", HttpHeaderCode::kHttpHeaderStrictTransportSecurity);
		init_map("TE", HttpHeaderCode::kHttpHeaderTe);
		init_map("Timestamp", HttpHeaderCode::kHttpHeaderTimestamp);
		init_map("Trailer", HttpHeaderCode::kHttpHeaderTrailer);
		init_map("Transfer-Encoding", HttpHeaderCode::kHttpHeaderTransferEncoding);
		init_map("Upgrade", HttpHeaderCode::kHttpHeaderUpgrade);
		init_map("User-Agent", HttpHeaderCode::kHttpHeaderUserAgent);
		init_map("VIP", HttpHeaderCode::kHttpHeaderVip);
		init_map("Vary", HttpHeaderCode::kHttpHeaderVary);
		init_map("via", HttpHeaderCode::kHttpHeaderVia);
		init_map("WWW-Authenticate", HttpHeaderCode::kHttpHeaderWWWAuthenticate);
		init_map("Warning", HttpHeaderCode::kHttpHeaderWarning);
		init_map("Accept", HttpHeaderCode::kHttpHeaderAccept);
		init_map("Accept-Charset", HttpHeaderCode::kHttpHeaderAcceptCharset);
		init_map("Accept-Datetime", HttpHeaderCode::kHttpHeaderAcceptDatetime);
		init_map("Accept-Encoding", HttpHeaderCode::kHttpHeaderAcceptEncoding);
		init_map("Accept-Language", HttpHeaderCode::kHttpHeaderAcceptLanguage);
		init_map("Accept-Ranges", HttpHeaderCode::kHttpHeaderAcceptRange);
		init_map("Access-Control-Allow-Credentials", HttpHeaderCode::kHttpHeaderAccessControlAllowCredentials);
		init_map("Access-Control-Allow-Headers", HttpHeaderCode::kHttpHeaderAccessControlAllowHeaders);
		init_map("Access-Control-Allow-Methods", HttpHeaderCode::kHttpHeaderAccessControlAllowMethod);
		init_map("Access-Control-Allow-Origin", HttpHeaderCode::kHttpHeaderAccessControlAllowOrigin);
		init_map("Access-Control-Expose-Headers", HttpHeaderCode::kHttpHeaderAccessControlExposeHeaders);
		init_map("Access-Control-Max-Age", HttpHeaderCode::kHttpHeaderAccessControlMaxAge);
		init_map("Access-Control-Request-Headers", HttpHeaderCode::kHttpHeaderAccessControlRequestHeaders);
		init_map("Access-Control-Request-Method", HttpHeaderCode::kHttpHeaderAccessControlRequestMethod);
		init_map("Age", HttpHeaderCode::kHttpHeaderAge);
		init_map("Allow", HttpHeaderCode::kHttpHeaderAllow);
		init_map("Alt-Svc", HttpHeaderCode::kHttpHeaderAltSvc);
		init_map("Authorization", HttpHeaderCode::kHttpHeaderAuthorization);
		init_map("X-Accel-Redirect", HttpHeaderCode::kHttpHeaderXAccelRedirect);
		init_map("X-Content-Security-Policy-Report-Only", HttpHeaderCode::kHttpHeaderXContentSecurityPolicyReportOnly);
		init_map("X-Content-Type-Options", HttpHeaderCode::kHttpHeaderXContentTypeOptions);
		init_map("X-Forwarded-For", HttpHeaderCode::kHttpHeaderXForwardedFor);
		init_map("X-Forwarded-Proto", HttpHeaderCode::kHttpHeaderXForwardedProto);
		init_map("X-Frame-Options", HttpHeaderCode::kHttpHeaderXFrameOption);
		init_map("X-Powered-By", HttpHeaderCode::kHttpHeaderXPoweredby);
		init_map("X-Real-IP", HttpHeaderCode::kHttpHeaderXRealIP);
		init_map("X-Requested-With", HttpHeaderCode::kHttpHeaderXrequestWith);
		init_map("X-UA-Compatible", HttpHeaderCode::kHttpHeaderXUACompatible);
		init_map("X-Wap-Profile", HttpHeaderCode::kHttpHeaderXWapProfile);
		init_map("X-XSS-Protection", HttpHeaderCode::kHttpHeaderXXSSProtection);
		init_map("F-Debug", HttpHeaderCode::kHttpHeaderFDebug);			
	}
private:
	void init_map(const std::string &name, HttpHeaderCode code)
	{
		map[name] = code;
		rmap[code] = name;
	}
};

static CommonHeaderMap g_common_map;

HttpHeaderCode HttpCommonHeaders:: hash(const std::string & header)
{
	std::unordered_map<std::string, HttpHeaderCode>::iterator it = 
		g_common_map.map.find(std::string(header.data, header.size()));
	if(it != g_common_map.map.end()) {
		return it->second;
	}
	return HttpHeaderCode::kHttpHeaderOther;
}

const std::string* HttpCommonHeaders::getPointerToHeaderName(HttpHeaderCode code)
{
	std::unordered_map<std::string, HttpHeaderCode>::iterator it = 
		g_common_map.rmap.find(code);
	if(it != g_common_map.map.end()) {
		return &(it->second);
	}
	return NULL;
}

}
}